﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Spider.Entitys.Spider;
using SpiderCore.DB;
using Newtonsoft.Json;
using System.IO;
using SpiderCore.Loggers;

namespace SpiderCore.Scheduler
{
    public class RedisScheduler : IScheduler
    {
        /// <summary>
        /// 初始化日志类型
        /// </summary>
        private readonly ISpiderLogger log = new SpiderMongoDBLog(typeof(RedisScheduler));
        /// <summary>
        /// 当前网站索引
        /// </summary>
        private int _currentIndex = 0;
        private const string RedisQueueRequestUrlFormat = "spider:request:{0}";
        private RedisDb db = new RedisDb();
        private List<string> _domainList = new List<string>();
        private string _currentRedisKey = "spider:list";
        private readonly string _filename = "domain.txt";
        public RedisScheduler()
        {
            LoadDomainList();

            SetCurrentRedisKey();
        }

        public void InitdomainList(List<string> list)
        {
            if (list != null && list.Count > 0)
            {
                _domainList = list;
            }
        }

        public RequestModel Pop()
        {
            if (_domainList.Any() == false) return null;
            RequestModel entity = null;
            try
            {
                entity = db.ListRightPop<RequestModel>(_currentRedisKey);
                return entity;
            }
            catch (Exception ex)
            {
                log.Fatal(ex, "Redis.Pop 错误");
                entity = Pop();
            }
            return entity;
        }

        public bool Push(RequestModel request)
        {
            try
            {
                if (request == null) return false;
                request.UrlHash = request.Url.ToMD5_UTF8();
                var json = JsonConvert.SerializeObject(request);
                var uri = new Uri(request.Url);
                //var redisKey = string.Format(RedisQueueRequestUrlFormat, uri.Host).ToLower();

                db.ListLeftPush(_currentRedisKey, json);
                if (_domainList.Contains(uri.Host) == false)
                {
                    _domainList.Add(uri.Host);
                }
            }
            catch (Exception ex)
            {
                log.Fatal(ex, "Redis.Push 错误");
            }
            return true;
        }

        public void Switch()
        {
            if (_currentIndex >= _domainList.Count)
            {
                _currentIndex = 0;
            }
            else
            {
                _currentIndex++;
            }

            SetCurrentRedisKey();
        }


        private void SetCurrentRedisKey()
        {
            if (_domainList.Count == 0 || _currentIndex >= _domainList.Count) return;

            var domain = _domainList[_currentIndex];

            _currentRedisKey = string.Format(RedisQueueRequestUrlFormat, domain).ToLower();
        }

        private void LoadDomainList()
        {
            if (File.Exists(_filename) == false)
            {
                File.WriteAllText(_filename, String.Empty, Encoding.UTF8);
            }

            _domainList = File.ReadAllLines(_filename, Encoding.UTF8).Distinct().Select(p => p.ToLower()).ToList();

        }
    }
}
